package aor2.cpu.blockinterrupt;

import aor2.components.FlipFlopException;
import aor2.components.FlipFlopRS;
import aor2.components.Restorable;
import aor2.components.Signal;
import aor2.cpu.blockcontrol.ConditionSignalSet;
import aor2.cpu.blockcontrol.ControlSignalSet;
import aor2.cpu.blockregisters.InstructionSignal;

public class InternInterruptBoard implements Restorable {
	FlipFlopRS ffprcod, ffpradr, ffprins;
	Signal stprins, clprins, prins, stpradr, clpradr, pradr, ldprcod,
			unknowninst, stprcod, clprcod, clrprcod, prcod;
	boolean clkFstPhase;

	public InternInterruptBoard() {
		ControlSignalSet ctrlss = ControlSignalSet.getInstance();
		clprcod = ctrlss.get("clprcod");
		clpradr = ctrlss.get("clpradr");
		clprins = ctrlss.get("clprins");
		stpradr = ctrlss.get("stpradr");
		stprins = ctrlss.get("stprins");
		ldprcod = ctrlss.get("ldprcod");

		ConditionSignalSet condss = ConditionSignalSet.getInstance();
		prins = condss.get("PRINS");
		pradr = condss.get("PRADR");
		prcod = condss.get("PRCOD");

		unknowninst = InstructionSignal.UNKNOWN.getSignal();

		stprcod = new Signal(false);
		clrprcod = new Signal(false);

		ffprcod = new FlipFlopRS(clrprcod, stprcod, prcod);
		ffpradr = new FlipFlopRS(clpradr, stpradr, pradr);
		ffprins = new FlipFlopRS(clrprcod, stprcod, prcod);

		clkFstPhase = true;
	}

	public void next() {

		if (clkFstPhase) {
			if (ldprcod.isActive()) {
				stprcod.setActive(unknowninst.isActive());
				clrprcod.setActive(!unknowninst.isActive());
			} else {
				stprcod.setActive(false);
				clrprcod.setActive(clprcod.isActive());
			}
			try {
				ffprcod.out();
				ffpradr.out();
				ffprins.out();
			} catch (FlipFlopException e) {
				e.printStackTrace();
			}

		} else {
			try {
				ffprcod.in();
				ffpradr.in();
				ffprins.in();
			} catch (FlipFlopException e) {
				e.printStackTrace();
			}
		}
		clkFstPhase = !clkFstPhase;
	}

	public Signal getStprins() {
		return stprins;
	}

	public Signal getStpradr() {
		return stpradr;
	}

	public Signal getStprcod() {
		return stprcod;
	}

	public Signal getClrprcod() {
		return clrprcod;
	}

	public void restore(String restorePoint) {
		String trim = restorePoint.replace(beginTag(), "");
		trim = trim.replace(endTag(), "");
		trim = trim.trim();
		String[] states = trim.split(" ");
		int i = 0;

		stprcod.clearHistory();
		clrprcod.clearHistory();

		stprcod.setActive(Boolean.parseBoolean(states[i++]));
		clrprcod.setActive(Boolean.parseBoolean(states[i++]));

		clkFstPhase = Boolean.parseBoolean(states[i++]);
	}

	@Override
	public String createRestorePoint() {
		return beginTag() + "\n\t" +

		stprcod.isActive() + " " + clrprcod.isActive() + " " +

		clkFstPhase + "\n" + endTag();
	}

	@Override
	public String beginTag() {
		return "<IIB>";
	}

	@Override
	public String endTag() {
		return "</IIB>";
	}

	public void previousClk() {
		clkFstPhase = true;

		stprcod.previousClk();
		clrprcod.previousClk();

		ffprcod.previousClk();
		ffpradr.previousClk();
		ffprins.previousClk();
	}

}
